﻿#region Imports
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using BulkRenamer.Util;
using CommonUtilities.Enums;
using CommonUtilities.Extensions;
using CommonUtilities.Messages;
using CommonUtilities.Util;
using Microsoft.VisualBasic;
#endregion

namespace BulkRenamer.Sampler
{
    public partial class frmSampler : Form
    {
        #region Declarations
        private readonly string sLoadBrowse = "&Load" + Utilities.cDelim + "&Browse";
        private readonly string sSaveGenerate = "&Save" + Utilities.cDelim + "&Generate";
        private readonly string sFileSamplesPath = Application.StartupPath + @"\FileNames.txt";
        private const string sSeparator = "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=";
        private const string sTab = "     ";

        public bool IsStandAlone { get; set; }
        #endregion

        #region Properties
        public ObservableCollection<SingletonValueWrapper<string>> AllPaths { get; set; }

        public bool IsDebug { get; set; }
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new default instance of <code>BulkRenamer.Sampler.frmSampler</code>
        /// </summary>
        public frmSampler()
        {
            StackTrace stkTrace = new StackTrace();
            StackFrame[] stkFrames = stkTrace.GetFrames();

            IsStandAlone = true;
            InitializeComponent();
            BRUtilities.CopyDesign(lstPaths, txtFileNames, false);
        }

        /// <summary>
        /// Initializes a new instance of <code>BulkRenamer.Sampler.frmSampler</code>
        /// with the specified path and sets the debug mode
        /// </summary>
        /// <param name="isDebug">Debug mode</param>
        /// <param name="defaultPath">Default path for sampling</param>
        public frmSampler(bool isDebug, string defaultPath = "")
            : this()
        {
            IsDebug = isDebug;
            IsStandAlone = true;

            txtFileNames.Visible = false;
            txtPath.Text = (!defaultPath.IsNullOrEmpty()) ? defaultPath : Application.StartupPath;
        }

        /// <summary>
        /// Initializes a new instance of <code>BulkRenamer.Sampler.frmSampler</code>
        /// with selected path and file names from Bulk Renamer
        /// </summary>
        /// <param name="isDebug">Debug mode</param>
        /// <param name="selectedPath">Selected path in Bulk Renamer</param>
        /// <param name="selectedFileNames">Selected file names in Bulk Renamer</param>
        public frmSampler(bool isDebug, string selectedPath, IEnumerable<string> selectedFileNames)
            : this()
        {
            IsDebug = isDebug;
            IsStandAlone = false;

            txtFileNames.Visible = false;
            txtPath.ReadOnly = true;
            txtPath.Text = selectedPath;
            btnLoadBrowse.Enabled = false;

            AllPaths = new ObservableCollection<SingletonValueWrapper<string>>(SingletonValueWrapper<string>
                .ConvertToSingletonValueWrapper(selectedFileNames));
            LoadFiles();
        }
        #endregion

        #region Events
        private void frmSampler_Load(object sender, EventArgs e)
        {
            EvaluateButtonText(Form.ModifierKeys);
            if (IsStandAlone) btnLoadBrowse_Click(null, e);
        }

        /// <summary>
        /// Occurs when the Load-Browse button is clicked
        /// </summary>
        private void btnLoadBrowse_Click(object sender, EventArgs e)
        {
            txtFileNames.Visible = false;

            #region Browse folder for files
            if (Form.ModifierKeys == Keys.Control)
            {
                FolderBrowserDialog dlgFolderBrowser = new FolderBrowserDialog
                {
                    Description = ResourceSampler.Msg_BrowseSamplingFolder,
                    SelectedPath = (txtPath.Text.ValidatePath(ePathValidation.Directory) ? txtPath.Text : Environment.SpecialFolder.MyComputer.GetFolderPath())
                };

                if (dlgFolderBrowser.ShowDialog(this) == DialogResult.OK)
                {
                    txtPath.Text = dlgFolderBrowser.SelectedPath;

                    dlgFolderBrowser.Dispose();
                    dlgFolderBrowser = null;
                }
            }
            #endregion

            #region Load files from folder
            else
            {
                string basePath = txtPath.Text;
                if (basePath.ValidatePath(ePathValidation.Directory))
                {
                    AllPaths = new ObservableCollection<SingletonValueWrapper<string>>(SingletonValueWrapper<string>.ConvertToSingletonValueWrapper(Utilities.GetValidFiles(basePath).Select(file => Path.GetFileName(file))));
                    LoadFiles();
                }
            }
            #endregion
        }

        /// <summary>
        /// Occurs when the Save-Generate button is clicked
        /// </summary>
        private void btnSaveGenerate_Click(object sender, EventArgs e)
        {
            #region Generate sample files to folder
            if (Form.ModifierKeys == Keys.Control)
            {
                if (!txtFileNames.Visible)
                {
                    txtFileNames.Visible = true;
                    mnuLoadGenerateFiles_Click(sender, e);
                }
                else
                {
                    if (txtFileNames.SelectionLength > 0)
                    {
                        ObservableCollection<string> fileNames
                            = txtFileNames.SelectedText.ConvertStringToLines().RemoveEmptyLines().ToObservableCollection();

                        if (fileNames.Any())
                        {
                            string folderName = Utilities.GetSuggestedPattern(fileNames, eTrimDirection.Left).Trim('\'');
                            folderName = Interaction.InputBox(ResourceSampler.Msg_GenerateSamples, ResourceSampler.App_GenerateSamples, folderName).Trim();
                            folderName = Application.StartupPath.AppendPath(ResourceSampler.Const_SamplesRoot, (!folderName.IsNullOrEmpty() ? folderName : DateTime.Now.ToString(ResourceSampler.Const_DefaultFolder_Format)));
                            if (!folderName.ValidatePath(ePathValidation.Directory)) Directory.CreateDirectory(folderName);

                            // Create files
                            fileNames.ForEach(fl => File.CreateText(folderName.AppendPath(fl)));

                            Clipboard.SetText(folderName);
                            MessageBox.Show(ResourceSampler.Msg_SamplingComplete.FormatTextFromParams(fileNames.LongCount(), (fileNames.LongCount() > 1 ? "s" : ""), folderName.GetDirectoryNameOnly(), sTab), ResourceSampler.App_Done, MessageBoxButtons.OK, MessageBoxIcon.Information);
                            Utilities.OpenPath(folderName);
                        }
                        else MessageBox.Show(ResourceSampler.Msg_GenerateSamples_NoFiles, ResourceSampler.App_GenerateSamples_NoFiles, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    else MessageBox.Show(ResourceSampler.Msg_GenerateSamples_NoSelection, ResourceSampler.App_GenerateSamples_NoSelection, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            #endregion

            #region Save sample file names to list
            else
            {
                if (txtFileNames.Visible)
                {
                    //MessageBox.Show("Please close sample generation preview to proceed..", "Sample preview error", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    MessageBox.Show(ResourceSampler.Msg_SamplePreviewOpen, ResourceSampler.App_SamplePreviewOpen, MessageBoxButtons.OK, MessageBoxIcon.Information);
                    txtFileNames.Visible = false;

                    return;
                }
                else
                {
                    if (AllPaths.IsLinqIterable<SingletonValueWrapper<string>>(true))
                    {
                        if (!sFileSamplesPath.ValidatePath(ePathValidation.File))
                        {
                            Utilities.CreateFile(sFileSamplesPath);
                            MessageBoxUtil.Show(IsDebug, ResourceSampler.Msg_NoOutputFile, ResourceSampler.App_NoOutputFile, MessageBoxButtons.OK, MessageBoxIcon.Information);
                        }

                        ObservableCollection<string> fileCache = File.ReadAllLines(sFileSamplesPath).Distinct().ToObservableCollection();

                        int sampleCount = 0;
                        AllPaths.ForEach(svw =>
                        {
                            //if (!fileCache._Contains(svw.SingletonValue))
                            {
                                sampleCount++;
                                File.AppendAllText(sFileSamplesPath, svw.SingletonValue + Utilities.cNewLine, Encoding.Unicode);
                            }
                        });
                        File.AppendAllText(sFileSamplesPath, sSeparator + Utilities.cNewLine, Encoding.Unicode);

                        // Finished
                        MessageBox.Show(ResourceSampler.Msg_SaveToCache_Done.FormatTextFromParams(sampleCount, AllPaths.LongCount(), (AllPaths.LongCount() > 1 ? "s" : "")), ResourceSampler.App_Done);
                        txtFileNames.ClearUndo();
                        txtFileNames.Clear();

                        if (IsStandAlone) lstPaths.DataSource = new ObservableCollection<object>();
                        else { MessageBoxUtil.Show(IsDebug, ResourceSampler.Msg_ClosingSampler); this.Close(); }
                    }
                }
            }
            #endregion
        }

        /// <summary>
        /// Occurs when a key is pressed on lstPaths control
        /// <para>Validates the characters being typed</para>
        /// </summary>
        private void lstPaths_KeyDown(object sender, KeyEventArgs e)
        {
            if (lstPaths.SelectedItems.Count > 0)
            {
                if (Form.ModifierKeys == Keys.Control)
                {
                    if (e.KeyCode == Keys.Delete)
                    {
                        ObservableCollection<SingletonValueWrapper<string>> del = new ObservableCollection<SingletonValueWrapper<string>>(
                            SingletonValueWrapper<string>.ConvertToSingletonValueWrapper(lstPaths.SelectedItems.Cast<SingletonValueWrapper<string>>().Select(svw => svw.SingletonValue)));

                        AllPaths = new ObservableCollection<SingletonValueWrapper<string>>(AllPaths.Where(file => !del.Select(d => d.SingletonValue).Contains(file.SingletonValue)));
                        LoadFiles();
                    }
                }
            }
        }

        private void btnMultiFunc_MouseEnter(object sender, EventArgs e)
        {
            EvaluateButtonText(Form.ModifierKeys);

            tltipSampler.ShowAlways = true;
            tltipSampler.Show(tltipSampler.GetToolTip((Control)sender), this);
        }

        private void btnMultiFunc_MouseLeave(object sender, EventArgs e)
        {
            EvaluateButtonText(Form.ModifierKeys);

            tltipSampler.Hide(this);
            tltipSampler.ShowAlways = false;
        }

        private void frmSampler_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Control) EvaluateButtonText(e.KeyCode);
        }

        private void frmSampler_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Control) EvaluateButtonText(Keys.None);
        }

        /// <summary>
        /// Occurs when the Load-Generate menu is clicked
        /// </summary>
        private void mnuLoadGenerateFiles_Click(object sender, EventArgs e)
        {
            if (!sFileSamplesPath.ValidatePath(ePathValidation.File))
            {
                MessageBoxUtil.Show(IsDebug, ResourceSampler.Msg_FileNotExist, ResourceSampler.App_Validation, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            txtFileNames.Text = File.ReadAllText(sFileSamplesPath, Encoding.Unicode);
            txtFileNames.Visible = true;
            txtFileNames.Focus();
            SendKeys.Send("{End}");
        }

        private void txtFileNames_VisibleChanged(object sender, EventArgs e)
        {
            btnClose.Visible = ((Control)sender).Visible;
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            txtFileNames.Visible = false;
        }
        #endregion

        #region Methods
        private void EvaluateButtonText(Keys modifierKeys)
        {
            if (modifierKeys == Keys.Control)
            {
                btnLoadBrowse.Text = sLoadBrowse.Split(Utilities.cDelim).Last();
                btnSaveGenerate.Text = sSaveGenerate.Split(Utilities.cDelim).Last();
            }
            else
            {
                btnLoadBrowse.Text = sLoadBrowse.Split(Utilities.cDelim).First();
                btnSaveGenerate.Text = sSaveGenerate.Split(Utilities.cDelim).First();
            }
        }

        private void LoadFiles()
        {
            SingletonValueWrapper<string>.BindToControl(AllPaths, lstPaths);
        }
        #endregion
    }
}
